from machine import Pin
import time
import network
import socket
import gc

# 配置参数
WIFI_SSID = "LAPTOP-D3RPTUAA 6358"
WIFI_PASSWORD = "19234949992.ch"
LED_PIN = 5
CHUNK_SIZE = 512
SEND_DELAY = 0.05

def init_led(pin=LED_PIN):
    """初始化LED引脚，返回LED对象"""
    led = Pin(pin, Pin.OUT)
    return led

def connect_wifi(ssid, password, led):
    """连接WiFi网络，返回连接状态和IP地址"""
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    
    if wlan.isconnected():
        wlan.disconnect()
    
    wlan.connect(ssid, password)
    
    timeout = 20
    while timeout > 0:
        if wlan.isconnected():
            print("WiFi连接成功!")
            ip_addr = wlan.ifconfig()[0]
            print(f"IP地址: {ip_addr}")
            led.off()
            return (True, ip_addr)
        
        timeout -= 1
        led.on()
        time.sleep(0.5)
        led.off()
        time.sleep(0.5)
        print(f"等待连接...({timeout}秒)")

    print("WiFi连接超时!")
    led.on()
    return (False, None)

def generate_html():
    """生成HTML页面内容"""
    html = """<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>六足机器人上位机</title>
    <style>
        /* 基础样式 */
        body { font-family: Arial, sans-serif; margin: 0; padding: 1rem; background-color: #f8fafc; }
        .container { background-color: white; border-radius: 0.5rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1); padding: 1rem; margin-bottom: 1rem; }
        h2 { font-size: 1.2rem; font-weight: bold; margin-bottom: 0.5rem; }
        
        /* 按钮样式 */
        .control-btn { width: 3rem; height: 3rem; display: flex; align-items: center; justify-content: center; 
                      background-color: #e2e8f0; color: #334155; border-radius: 0.5rem; cursor: pointer; }
        .control-btn:active { background-color: #cbd5e1; }
        
        /* 摄像头区域 */
        .video-container { height: 12rem; background-color: #f1f5f9; border-radius: 0.5rem; position: relative; overflow: hidden; }
        .video-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; }
        .animate-pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
        
        /* 雷达区域 */
        .radar-container { height: 12rem; background-color: #0f172a; border-radius: 0.5rem; position: relative; }
        
        /* 机器人控制区域 */
        .robot-arena { height: 12rem; background-color: #f1f5f9; border-radius: 0.5rem; position: relative; }
        
        /* 传感器卡片 */
        .sensor-card { background-color: #f1f5f9; border-radius: 0.375rem; padding: 0.5rem; margin-bottom: 0.5rem; }
        .sensor-label { font-size: 0.75rem; color: #64748b; }
        .sensor-value { font-size: 1.1rem; font-weight: 600; }
    </style>
    <script>
        const esp32Data = {
            isConnected: false,
            robotStatus: {
                position: { x: 50, y: 50 },
                direction: 0,
                gait: 'triangle'
            }
        };

        document.addEventListener('DOMContentLoaded', () => {
            initVideoStream();
            initRobotControl();
            initRadar();
            initSensorDataSimulation();
        });

        // 摄像头模拟
        function initVideoStream() {
            const videoElement = document.getElementById('esp32-cam-video');
            const videoPlaceholder = document.getElementById('video-placeholder');
            const refreshButton = document.getElementById('refresh-video');
            const videoStatusDetail = document.getElementById('video-status-detail');
            
            // 强制连接成功
            const isConnectionSuccessful = true;
            
            setTimeout(() => {
                if (isConnectionSuccessful) {
                    videoPlaceholder.classList.add('hidden');
                    videoElement.classList.remove('hidden');
                    videoStatusDetail.textContent = '连接成功';
                    esp32Data.isConnected = true;
                } else {
                    videoStatusDetail.textContent = '连接失败';
                    videoStatusDetail.classList.add('text-red-500');
                    esp32Data.isConnected = false;
                }
            }, 1000);

            refreshButton.addEventListener('click', () => {
                videoElement.classList.add('hidden');
                videoPlaceholder.classList.remove('hidden');
                videoStatusDetail.textContent = '重新连接...';
                setTimeout(() => {
                    videoPlaceholder.classList.add('hidden');
                    videoElement.classList.remove('hidden');
                    videoStatusDetail.textContent = '连接成功';
                    esp32Data.isConnected = true;
                }, 1000);
            });
        }

        // 机器人控制
        function initRobotControl() {
            const robot = {
                element: document.getElementById('robot'),
                commandDisplay: document.getElementById('current-command'),
                gaitDisplay: document.getElementById('gait-mode'),
                updateDisplay() {
                    this.element.style.left = `${esp32Data.robotStatus.position.x}%`;
                    this.element.style.top = `${esp32Data.robotStatus.position.y}%`;
                    this.element.style.transform = `rotate(${esp32Data.robotStatus.direction * 90}deg)`;
                    this.gaitDisplay.textContent = esp32Data.robotStatus.gait.charAt(0).toUpperCase() + esp32Data.robotStatus.gait.slice(1);
                }
            };

            const keyMappings = {
                'w': 'up',
                's': 'down',
                'a': 'left',
                'd': 'right'
            };

            function moveRobot(direction) {
                const speed = 5;
                const arena = document.querySelector('.robot-arena');
                const arenaRect = arena.getBoundingClientRect();
                const robotSize = robot.element.offsetWidth;
                const maxX = 100 - (robotSize / arenaRect.width * 100);
                const maxY = 100 - (robotSize / arenaRect.height * 100);

                const prevX = esp32Data.robotStatus.position.x;
                const prevY = esp32Data.robotStatus.position.y;

                switch(direction) {
                    case 'up':
                        esp32Data.robotStatus.position.y = Math.max(0, prevY - speed);
                        esp32Data.robotStatus.direction = 0;
                        break;
                    case 'down':
                        esp32Data.robotStatus.position.y = Math.min(maxY, prevY + speed);
                        esp32Data.robotStatus.direction = 2;
                        break;
                    case 'left':
                        esp32Data.robotStatus.position.x = Math.max(0, prevX - speed);
                        esp32Data.robotStatus.direction = 3;
                        break;
                    case 'right':
                        esp32Data.robotStatus.position.x = Math.min(maxX, prevX + speed);
                        esp32Data.robotStatus.direction = 1;
                        break;
                }

                robot.updateDisplay();
                robot.commandDisplay.textContent = direction;
            }

            // 绑定按钮事件
            document.getElementById('btn-up').addEventListener('click', () => moveRobot('up'));
            document.getElementById('btn-down').addEventListener('click', () => moveRobot('down'));
            document.getElementById('btn-left').addEventListener('click', () => moveRobot('left'));
            document.getElementById('btn-right').addEventListener('click', () => moveRobot('right'));

            // 绑定键盘事件
            document.addEventListener('keydown', (e) => {
                const direction = keyMappings[e.key.toLowerCase()];
                if (direction) {
                    e.preventDefault();
                    moveRobot(direction);
                }
            });
        }

        // 雷达点云图（恢复白色）
        let radarCanvas, radarCtx;
        let radarRotation = 0;

        function initRadar() {
            radarCanvas = document.getElementById('radar-canvas');
            if (!radarCanvas) return;
            
            radarCtx = radarCanvas.getContext('2d');
            resizeRadarCanvas();
            
            // 降低刷新率
            setInterval(drawRadar, 100);
        }

        function resizeRadarCanvas() {
            radarCanvas.width = radarCanvas.offsetWidth;
            radarCanvas.height = radarCanvas.offsetHeight;
            drawRadar();
        }

        function drawRadar() {
            radarCtx.clearRect(0, 0, radarCanvas.width, radarCanvas.height);
            drawRadarBackground();
            
            // 绘制扫描线（恢复白色）
            const centerX = radarCanvas.width / 2;
            const centerY = radarCanvas.height / 2;
            const maxRadius = Math.min(centerX, centerY) * 0.9;
            
            radarCtx.strokeStyle = 'white';
            radarCtx.lineWidth = 1;
            radarCtx.beginPath();
            radarCtx.moveTo(centerX, centerY);
            radarCtx.lineTo(
                centerX + Math.cos(radarRotation) * maxRadius,
                centerY + Math.sin(radarRotation) * maxRadius
            );
            radarCtx.stroke();
            
            // 绘制扇形扫描区域
            const gradient = radarCtx.createRadialGradient(
                centerX, centerY, 0,
                centerX, centerY, maxRadius
            );
            
            gradient.addColorStop(0, 'rgba(255, 255, 255, 0.1)');
            gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
            
            radarCtx.fillStyle = gradient;
            radarCtx.beginPath();
            radarCtx.moveTo(centerX, centerY);
            radarCtx.arc(centerX, centerY, maxRadius, radarRotation - 0.3, radarRotation);
            radarCtx.closePath();
            radarCtx.fill();
            
            // 更新旋转角度
            radarRotation += 0.03;
            if (radarRotation > Math.PI * 2) {
                radarRotation -= Math.PI * 2;
            }
        }

        function drawRadarBackground() {
            // 绘制背景（恢复白色网格）
            radarCtx.fillStyle = '#000';
            radarCtx.fillRect(0, 0, radarCanvas.width, radarCanvas.height);
            
            radarCtx.strokeStyle = 'rgb(255,255,255)';
            radarCtx.lineWidth = 1;
            
            const centerX = radarCanvas.width / 2;
            const centerY = radarCanvas.height / 2;
            const maxRadius = Math.min(centerX, centerY) * 0.9;
            
            // 绘制同心圆
            for (let i = 1; i <= 3; i++) {
                const radius = (maxRadius / 3) * i;
                radarCtx.beginPath();
                radarCtx.arc(centerX, centerY, radius, 0, Math.PI * 2);
                radarCtx.stroke();
            }
            
            // 绘制十字线
            radarCtx.beginPath();
            radarCtx.moveTo(centerX - maxRadius, centerY);
            radarCtx.lineTo(centerX + maxRadius, centerY);
            radarCtx.moveTo(centerX, centerY - maxRadius);
            radarCtx.lineTo(centerX, centerY + maxRadius);
            radarCtx.stroke();
        }

        // 传感器数据模拟
        function initSensorDataSimulation() {
            let temp = 25.6;
            let humidity = 48.2;
            let batteryVoltage = 7.8;
            
            setInterval(() => {
                temp += (Math.random() - 0.5) * 0.4;
                document.getElementById('temp-value').textContent = temp.toFixed(1) + '°C';
                
                humidity += (Math.random() - 0.5) * 1.2;
                document.getElementById('humidity-value').textContent = humidity.toFixed(1) + '%';
                
                batteryVoltage -= 0.001;
                document.getElementById('battery-voltage').textContent = batteryVoltage.toFixed(1) + 'V';
                
                const mcu = 20 + Math.random() * 30;
                document.getElementById('MCUoccupy-value').textContent = mcu.toFixed(0) + '%';
            }, 5000); // 降低更新频率
        }
    </script>
</head>
<body>
    <h1 class="text-center text-xl font-bold mb-4">六足机器人上位机</h1>
    
    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
        <!-- 摄像头区域 -->
        <div class="container">
            <h2>摄像头</h2>
            <div class="video-container">
                <div id="video-placeholder" class="video-placeholder">
                    <div class="animate-pulse rounded-full h-12 w-12 bg-gray-300 mb-2"></div>
                    <p class="text-gray-500">正在连接...</p>
                </div>
                <img id="esp32-cam-video" src="" alt="摄像头模拟图像" class="w-full h-full object-cover hidden">
                <button id="refresh-video" class="absolute bottom-2 right-2 bg-white/80 hover:bg-white text-primary p-1 rounded-full shadow-md">
                    <i class="fa fa-refresh"></i>
                </button>
            </div>
            <div class="mt-1 text-sm text-gray-500">
                <span id="video-status">状态: <span id="video-status-detail">连接中...</span></span>
            </div>
        </div>
        
        <!-- 机器人控制区域 -->
        <div class="container">
            <h2>机器人控制</h2>
            <div class="grid grid-cols-3 gap-2 w-36 mx-auto mb-3">
                <div class="col-span-3 flex justify-center">
                    <button id="btn-up" class="control-btn">W</button>
                </div>
                <div class="col-span-3 grid grid-cols-3 gap-2">
                    <div class="col-start-1 flex justify-end">
                        <button id="btn-left" class="control-btn">A</button>
                    </div>
                    <div class="flex justify-center">
                        <button id="btn-down" class="control-btn">S</button>
                    </div>
                    <div class="flex justify-start">
                        <button id="btn-right" class="control-btn">D</button>
                    </div>
                </div>
            </div>
            <div class="robot-arena">
                <div id="robot" class="absolute w-8 h-8 bg-control rounded-full flex items-center justify-center text-white">
                    <i class="fa fa-arrow-up"></i>
                </div>
            </div>
            <div class="mt-1 text-sm text-gray-500">
                <span>当前指令:</span> <span id="current-command">等待输入...</span>
            </div>
        </div>
        
        <!-- 传感器数据区域 -->
        <div class="container">
            <h2>传感器数据</h2>
            <div class="grid grid-cols-2 gap-2">
                <div class="sensor-card">
                    <div class="sensor-label">环境温度</div>
                    <div class="sensor-value" id="temp-value">25.6°C</div>
                </div>
                <div class="sensor-card">
                    <div class="sensor-label">环境湿度</div>
                    <div class="sensor-value" id="humidity-value">48.2%</div>
                </div>
                <div class="sensor-card">
                    <div class="sensor-label">电池电压</div>
                    <div class="sensor-value" id="battery-voltage">7.8V</div>
                </div>
                <div class="sensor-card">
                    <div class="sensor-label">MCU占用</div>
                    <div class="sensor-value" id="MCUoccupy-value">20%</div>
                </div>
            </div>
        </div>
        
        <!-- 雷达区域 -->
        <div class="container">
            <h2>360°雷达点云图</h2>
            <div class="radar-container">
                <canvas id="radar-canvas" width="100%" height="100%"></canvas>
                <div class="absolute bottom-1 left-1 text-xs text-white/80">
                    <span id="radar-status">状态: 扫描中...</span>
                </div>
            </div>
        </div>
    </div>
</body>
</html>"""
    return html

def handle_client(cl, html_content):
    """处理客户端HTTP请求"""
    try:
        request = cl.recv(1024)
        cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
        
        total_sent = 0
        while total_sent < len(html_content):
            chunk = html_content[total_sent:total_sent + CHUNK_SIZE]
            cl.send(chunk)
            total_sent += len(chunk)
            time.sleep(SEND_DELAY)
            
            if total_sent % (CHUNK_SIZE * 4) == 0:
                gc.collect()
        
    except Exception as e:
        print(f"处理客户端请求错误: {e}")
    finally:
        cl.close()

def start_web_server(ip_addr, html_content):
    """启动Web服务器并处理客户端请求"""
    print(f'Web服务器已启动，访问: http://{ip_addr}')
    
    addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
    s = socket.socket()
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(addr)
    s.listen(1)
    
    try:
        while True:
            cl, client_addr = s.accept()
            print(f'客户端连接来自: {client_addr}')
            
            gc.collect()
            free_mem = gc.mem_free()
            print(f"处理请求前内存: {free_mem} 字节")
            
            handle_client(cl, html_content)
            
            gc.collect()
            free_mem = gc.mem_free()
            print(f"处理请求后内存: {free_mem} 字节")
            
    except Exception as e:
        print(f"Web服务器错误: {e}")
    finally:
        s.close()

# 主程序入口
if __name__ == "__main__":
    led = init_led()
    connected, ip = connect_wifi(WIFI_SSID, WIFI_PASSWORD, led)
    
    if connected:
        html = generate_html()
        start_web_server(ip, html)
    else:
        print("WiFi连接失败，程序退出")